package com.example.jimuyutabletcontrol.activity;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.jimuyutabletcontrol.R;
import com.example.jimuyutabletcontrol.adapter.fileadapter.SimpleAdapter;
import com.example.jimuyutabletcontrol.adapter.selectauvrecord.SelectAUVRecordAdapter;
import com.example.jimuyutabletcontrol.bean.AUVRecordDataInfo;
import com.example.jimuyutabletcontrol.network.tcp.ITCPSocket;
import com.example.jimuyutabletcontrol.network.tcp.TCPSocket;
import com.example.jimuyutabletcontrol.network.udp.UdpMessageHandle;
import com.example.jimuyutabletcontrol.network.udp.UdpMessageType;
import com.example.jimuyutabletcontrol.network.udp.UdpSocket;
import com.example.jimuyutabletcontrol.utils.Constants;
import com.kaopiz.kprogresshud.KProgressHUD;
import com.orhanobut.dialogplus.DialogPlus;
import com.orhanobut.dialogplus.DialogPlusBuilder;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.RecyclerView;

public class SelectAUVRecordDataActivity extends AppCompatActivity implements
        Toolbar.OnMenuItemClickListener, View.OnClickListener, OnRefreshLoadmoreListener {

    public KProgressHUD hud;
    private DialogPlus dialog;

    private UdpMessageHandle handle1;
    private UdpMessageHandle handle2;
    private Toolbar toolbar;

    private Point[] pentagonVertices;
    private Button[] buttons;
    private int width;
    private int radius;
    private int startPositionX;
    private int startPositionY;
    private int whichAnimation;
    private int NUM_OF_SIDES;
    private int[] enterDelay = {80, 120, 160, 40, 0, 200, 240};
    private int[] exitDelay = {80, 40, 0, 120, 160, 200, 240};
    private String[] content = {"数据分析"};

    private SmartRefreshLayout mSmartRefreshLayout;

    private RecyclerView mRecyclerView;

    private List<String> infos;

    private SelectAUVRecordAdapter adapter;

    /**
     * ==0,下拉刷新；==1，上拉加载
     */
    private int loadType = 0;

    private Map<String, List<AUVRecordDataInfo>> childDatas;

    private TextView noData;

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (dialog != null) {
            dialog.dismiss();
        }
        if (null != handle1) {
            UdpSocket.getInstance().removeMessageCallback(handle1);
            handle1 = null;
        }
        if (null != handle2) {
            UdpSocket.getInstance().removeMessageCallback(handle2);
            handle2 = null;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.selectauvrecorddatainterface_pull_to_refresh);
        initView();
        setAdapter();
        setListeners();
        mSmartRefreshLayout.autoRefresh();
        initData();
        prepareFloatButton();
    }

    private void initData() {
        childDatas = new HashMap<>();
    }

    private void setAdapter() {
        infos = new ArrayList<>();
        adapter = new SelectAUVRecordAdapter(infos);
        mRecyclerView.setAdapter(adapter);
    }

    private void initView() {
        toolbar = findViewById(R.id.toolbarrecorddata);
        toolbar.setTitle("AUV内记数据下载");
        setSupportActionBar(toolbar);
        mSmartRefreshLayout = findViewById(R.id.mSmartRefreshLayout);
        mRecyclerView = findViewById(R.id.mRecyclerView);
        noData = findViewById(R.id.noData);
    }

    private void setListeners() {
        if (toolbar != null) {
            toolbar.setOnMenuItemClickListener(this);
        }
        adapter.setOnSelectAUVRecordListener(position -> showDialogWithData(infos.get(position)));
        handle1 = new UdpMessageHandle(UdpMessageType.IMEI, msg -> {
            if (loadType == 0) {
                mSmartRefreshLayout.finishRefresh(true);
            } else {
                mSmartRefreshLayout.finishLoadmore(true);
            }
            updateListData(msg);
        });
        handle2 = new UdpMessageHandle(UdpMessageType.TXT, this::updateValue);
        UdpSocket.getInstance().setMessageCallback(handle1);
        UdpSocket.getInstance().setMessageCallback(handle2);
        mSmartRefreshLayout.setOnRefreshLoadmoreListener(this);
    }

    @Override
    public void onLoadmore(RefreshLayout refreshlayout) {
        UdpSocket.getInstance().sendMessage("INSTANTIMEI");
        UdpSocket.getInstance().sendMessage("INSTANTIMEIDATA");
        loadType = 1;
    }

    @Override
    public void onRefresh(RefreshLayout refreshlayout) {
        UdpSocket.getInstance().sendMessage("INSTANTIMEI");
        UdpSocket.getInstance().sendMessage("INSTANTIMEIDATA");
        loadType = 0;
    }

    private void updateListData(String message) {
        Log.e("updateListData", message);
        runOnUiThread(() -> {
            String[] contents = message.split(",");
            List<String> strs = new ArrayList<>();
            for (int i = 1; i < contents.length; i++) {
                if (!infos.contains(contents[i])) {
                    strs.add(contents[i]);
                }
            }
            if (strs.size() > 0) {
                int refreshindex = infos.size();
                infos.addAll(strs);
                adapter.notifyItemRangeInserted(refreshindex, strs.size());
            }
            noData.setVisibility((null == infos||infos.size()==0)?View.VISIBLE:View.GONE);
        });
    }

    private void updateValue(String message) {
        runOnUiThread(() -> {
            String[] content = message.split(",");
            String key = content[0];
            boolean isHas = false;
            int position = -1;
            if (childDatas.containsKey(key)) {
                List<AUVRecordDataInfo> list = childDatas.get(key);
                if (null != list) {
                    for (String str : content) {
                        if (str.contains(".txt")) {
                            for (AUVRecordDataInfo info : list) {
                                if (!TextUtils.isEmpty(info.textName) && info.textName.equals(str)) {
                                    isHas = true;
                                } else {
                                    if (TextUtils.isEmpty(info.textName)) {
                                        position = list.indexOf(info);
                                    }
                                }
                                if (TextUtils.isEmpty(info.imei) || !info.imei.equals(key)) {
                                    info.imei = key;
                                }
                            }
                            if (position != -1) {
                                list.remove(position);
                                position = -1;
                            }
                            if (!isHas) {
                                createNewsChildInfo(key, list, str);
                                isHas = false;
                            }
                        }
                    }
                } else {
                    List<AUVRecordDataInfo> newsList = new ArrayList<>();
                    for (String str : content) {
                        if (str.contains(".txt")) {
                            createNewsChildInfo(key, newsList, str);
                        }
                    }
                    childDatas.put(key, newsList);
                }
            } else {
                List<AUVRecordDataInfo> newsList = new ArrayList<>();
                for (String str : content) {
                    if (str.contains(".txt")) {
                        createNewsChildInfo(key, newsList, str);
                    }
                }
                childDatas.put(key, newsList);
            }
        });
    }

    private void createNewsChildInfo(String key, List<AUVRecordDataInfo> list, String str) {
        AUVRecordDataInfo dataInfo = new AUVRecordDataInfo();
        dataInfo.imei = key;
        dataInfo.textName = str;
        dataInfo.isDownload = isDownload(str);
        list.add(dataInfo);
    }


    private File dhFile;

    private File dsFile;

    private boolean isDownload(String fileName) {
        if (TextUtils.isEmpty(fileName) || !fileName.contains(".txt")) return false;
        if (null == dhFile) {
            dhFile = new File(Constants.FILE_PATH + Constants.DH);
        }
        if (null == dsFile) {
            dsFile = new File(Constants.FILE_PATH + Constants.DS);
        }
        if (!dhFile.exists()) {
            dhFile.mkdirs();
        }
        if (!dsFile.exists()) {
            dsFile.mkdirs();
        }
        File[] files;
        if (fileName.contains("DH")) {
            files = dhFile.listFiles();
        } else {
            files = dsFile.listFiles();
        }
        if (files.length == 0) {
            return false;
        }
        boolean isHas = false;
        for (File file : files) {
            if (!file.isDirectory()) {
                String name = file.getName();
                Log.e("fileName", name);
                if (name.equals(fileName)) {
                    isHas = true;
                }
            }
        }
        return isHas;
    }

    private void showDialogWithData(String imei) {
        if (childDatas.size() == 0 || !childDatas.containsKey(imei)) {
            toastMsg("没有AUV:" + imei + "相关数据");
            return;
        }
        List<AUVRecordDataInfo> list = childDatas.get(imei);
        if (null == list || list.size() == 0) {
            toastMsg("没有AUV:" + imei + "相关数据");
            return;
        }
        SimpleAdapter simpleAdapter = new SimpleAdapter(this, list);
        DialogPlusBuilder dialogPlusBuilder = DialogPlus.newDialog(this);
        dialogPlusBuilder.setAdapter(simpleAdapter);
        dialogPlusBuilder.setOnItemClickListener(((dialog1, item, view, position) -> toDownload(list.get(position), simpleAdapter)));
        dialogPlusBuilder.setExpanded(true);
        dialog = dialogPlusBuilder.create();
        dialog.show();
    }

    private void toDownload(AUVRecordDataInfo info, SimpleAdapter simpleAdapter) {
        if (info.isDownload){
            Toast.makeText(SelectAUVRecordDataActivity.this, "此数据已下载", Toast.LENGTH_SHORT).show();
            return;
        }
        hud = KProgressHUD
                .create(this)
                .setStyle(KProgressHUD.Style.SPIN_INDETERMINATE)
                .setLabel("请稍等")
                .setDetailsLabel("正在下载数据...");
        hud.show();
        ITCPSocket tcpSocket = TCPSocket.getInstance();
        tcpSocket.setNetTask(info.textName, () -> runOnUiThread(() -> {
            info.isDownload = true;
            simpleAdapter.notifyDataSetChanged();
            hud.dismiss();
            Toast.makeText(SelectAUVRecordDataActivity.this, "下载完毕", Toast.LENGTH_SHORT).show();
        }), () -> runOnUiThread(() -> {
            hud.dismiss();
            Toast.makeText(SelectAUVRecordDataActivity.this, "服务器无响应", Toast.LENGTH_SHORT).show();
        }));
        tcpSocket.downloadFile();
    }

    private void prepareFloatButton() {
        startPositionX = 0;
        startPositionY = 0;
        whichAnimation = 0;
        NUM_OF_SIDES = 1;
        width = 200;
        radius = 200;
        calculatePentagonVertices(radius, 11);
    }

    private void calculatePentagonVertices(int radius, int rotation) {

        pentagonVertices = new Point[NUM_OF_SIDES];

        /**
         * Calculating the center of pentagon
         */
        Display display = getWindowManager().getDefaultDisplay();
        int centerX = display.getWidth() / 2;
        int centerY = display.getHeight() / 2;

        /**
         * Calculating the coordinates of vertices of pentagon
         */
        for (int i = 0; i < NUM_OF_SIDES; i++) {
            pentagonVertices[i] = new Point((int) (radius * Math.cos(rotation + i * 2 * Math.PI / NUM_OF_SIDES)) + centerX,
                    (int) (radius * Math.sin(rotation + i * 2 * Math.PI / NUM_OF_SIDES)) + centerY - 100);
        }

        buttons = new Button[pentagonVertices.length];

        for (int i = 0; i < buttons.length; i++) {
            //Adding button at (0,0) coordinates and setting their visibility to zero
            buttons[i] = new Button(SelectAUVRecordDataActivity.this);
            buttons[i].setLayoutParams(new RelativeLayout.LayoutParams(100, 100));
            buttons[i].setX(0);
            buttons[i].setY(0);
            buttons[i].setTag(i);
            buttons[i].setOnClickListener(this);
            buttons[i].setVisibility(View.INVISIBLE);
            buttons[i].setBackgroundResource(R.drawable.circular_background);
            buttons[i].setTextColor(Color.DKGRAY);
            buttons[i].setText(content[i]);
            buttons[i].setTextSize(14);
            /**
             * Adding those buttons in acitvities layout
             */
            ((LinearLayout) findViewById(R.id.main_recorddata)).addView(buttons[i]);
        }
    }

    private void playEnterAnimation(final Button button, int position) {

        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(startPositionX + button.getLayoutParams().width / 2,
                pentagonVertices[position].x);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue() - button.getLayoutParams().width / 2);
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(startPositionY + 5,
                pentagonVertices[position].y);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will increase the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(5, width);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(enterDelay[position]);
        buttonAnimator.start();
    }


    @Override
    public void onClick(View view) {
        Intent intent = null;
        switch ((int) view.getTag()) {
            case 0:
                intent = new Intent(SelectAUVRecordDataActivity.this, SelectAUVAnalyseActivity.class);
                startActivity(intent);
                finish();
                break;
        }
    }

    private void playExitAnimation(final Button button, int position) {

        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(pentagonVertices[position].x - button.getLayoutParams().width / 2,
                startPositionX);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(pentagonVertices[position].y,
                startPositionY + 5);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will decrease the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(width, 5);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(exitDelay[position]);
        buttonAnimator.start();
    }


    private void toastMsg(final String msg) {
        runOnUiThread(() -> Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.selectauvrecorddatainterface_menu, menu);
        return true;
    }

    @Override
    public boolean onMenuItemClick(MenuItem menuItem) {
        if (menuItem.getItemId() == R.id.auvrecorddata_clear) {
            if (null != infos && infos.size() > 0) {
                infos.clear();
                adapter.notifyDataSetChanged();
                mSmartRefreshLayout.autoRefresh();
            }
        } else if (menuItem.getItemId() == R.id.send_recorddata) {
            if (whichAnimation == 0) {
                /**
                 * Getting the center point of floating action button
                 *  to set start point of buttons
                 */
                startPositionX = 2600;
                startPositionY = 0;
                for (Button button : buttons) {
                    button.setX(startPositionX);
                    button.setY(startPositionY);
                    button.setVisibility(View.VISIBLE);
                }
                for (int i = 0; i < buttons.length; i++) {
                    playEnterAnimation(buttons[i], i);
                }
                whichAnimation = 1;
            } else {
                for (int i = 0; i < buttons.length; i++) {
                    playExitAnimation(buttons[i], i);
                }
                whichAnimation = 0;
            }
            return true;
        }
        return false;
    }

}
